home *** CD-ROM | disk | FTP | other *** search
- /**** function.c ****/
- /* By Paul Field
- * See !ReadMe file for distribution/modification restrictions
- */
-
- #include "function.h"
- #include <float.h>
- #include <stdio.h>
-
- #define max(a,b) ((a)>(b)?(a):(b))
- #define min(a,b) ((a)<(b)?(a):(b))
-
-
- static os_error memerr = { 0, "Not enough memory - increase wimpslot." };
-
-
- /* Points on the graph are (X,Y,f(X,Y))
- */
-
- os_error *function_makegraph(euclid_header *h, graphdata *g, euclid_mesh **mesh)
- { double *results, *r;
- double minz,maxz; /* Maximum and minimum of the function */
- double rangex,rangey,rangez;
- double maxrange;
- double scale;
- double dy,dx; /* Change in function variables per square */
- double fx,fy; /* Function variables */
- int ax,ay; /* 'results' array indices */
- os_error *e;
-
- results = malloc((g->subdivisions+1)*(g->subdivisions+1)*sizeof(double));
- if (results == NULL)
- { return(&memerr);
- }
- rangex = g->maxx-g->minx;
- rangey = g->maxy-g->miny;
- dx = rangex/g->subdivisions;
- dy = rangey/g->subdivisions;
- minz = DBL_MAX;
- maxz = DBL_MIN;
- r = results;
-
- /* I'm using ax and ay because there may be rounding errors */
- /* and other problems with fx and fy if dx and dy are small. */
- for (ax = 0, fx = g->minx; ax <= g->subdivisions; ax++, fx += dx)
- { for (ay = 0, fy = g->miny; ay <= g->subdivisions; ay++, fy += dx)
- { *r = g->f(fx,fy);
- maxz = max(*r,maxz);
- minz = min(*r,minz);
- r++;
- }
- }
- rangez = maxz-minz;
- maxrange = max(rangex, rangey);
- maxrange = max(maxrange, rangez);
- scale = g->realsize/maxrange;
-
- if ((e = euclid_create(g->subdivisions+1, h, eid_mesh, mesh)) == NULL)
- { euclid_setname((*mesh)->name, g->name);
- r = results;
- for (ax = 0, fx = g->minx; ax <= g->subdivisions && !e; ax++, fx += dx)
- { euclid_vane *v;
-
- if ((e = euclid_create(g->subdivisions+1, h, eid_vane, &v)) == NULL)
- { (*mesh)->var[ax].colour.c.abscolour = euclid_makecolour(0x80u,0,0,0);
- (*mesh)->var[ax].vane = v;
- for (ay = 0, fy = g->miny; ay <= g->subdivisions; ay++, fy += dx)
- { struct euclid_vanevar *vv;
-
- vv = &v->var[ay];
- vv->colour1.c.abscolour = euclid_makecolour(0x80u,0xff,0xff,0xff);
- vv->colour2.c.abscolour = euclid_makecolour(0x80u,0xff,0xff,0xff);
- vv->point.x = (int)((fx-g->minx-rangex/2)*scale+0.5);
- vv->point.y = (int)((fy-g->miny-rangey/2)*scale+0.5);
- vv->point.z = (int)((*r++)*scale+0.5);
- }
- }
- }
- if (e)
- { for (ax--; ax >= 0; ax--)
- { euclid_destroy(h, (*mesh)->var[ax].vane);
- }
- euclid_destroy(h, *mesh);
- }
- }
- g->scale = scale;
- free(results);
- return(e);
- }
-